package org.jaaksi.svcmanager;

import android.database.Cursor;
import android.database.MatrixCursor;
import android.os.Bundle;
import android.os.IBinder;
import android.os.Parcel;
import android.os.Parcelable;

/**
 * ContentProvider的query方法返回的是一个Cursor，
 * 现在的场景不像查询数据库一样可以通过SQLiteDatabase的query方法直接返回一个Cursor，
 * 而Cursor又是一个接口，没有办法直接实例化。所以我们需要找一个可以实例化一个Cursor，这里用到了MatrixCursor。
 * 有了Cursor之后就可以把根据查询参数的不同我们返回了不同的binder放到Cursor中返回。
 */
public class BinderCursor extends MatrixCursor {

  static final String KEY_BINDER = "binder";
  static final String[] DEFAULT_COLUMNS = { "s" }; // 这个是任意的，没有意义，只是参数需要

  static final BinderCursor create(IBinder binder) {
    return new BinderCursor(DEFAULT_COLUMNS, binder);
  }

  static final IBinder getBinder(Cursor cursor) {
    if (cursor == null) return null;

    Bundle extras = cursor.getExtras();
    extras.setClassLoader(BinderParcelable.class.getClassLoader());
    BinderParcelable w = extras.getParcelable(KEY_BINDER);
    return w.mBinder;
  }

  /**
   * cursor可以携带bundle，将binder保存在bundle存传递，实现Parcelable接口
   */
  static class BinderParcelable implements Parcelable {

    public IBinder mBinder;

    public static final Creator<BinderParcelable> CREATOR = new Creator<BinderParcelable>() {
      @Override
      public BinderParcelable createFromParcel(Parcel source) {
        return new BinderParcelable(source);
      }

      @Override
      public BinderParcelable[] newArray(int size) {
        return new BinderParcelable[size];
      }
    };

    BinderParcelable(IBinder binder) {
      mBinder = binder;
    }

    BinderParcelable(Parcel source) {
      mBinder = source.readStrongBinder();
    }

    @Override
    public int describeContents() {
      return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
      dest.writeStrongBinder(mBinder);
    }
  }

  Bundle mBinderExtra = new Bundle();

  private BinderCursor(String[] columnNames, IBinder binder) {
    super(columnNames);
    if (binder != null) {
      Parcelable value = new BinderParcelable(binder);
      mBinderExtra.putParcelable(KEY_BINDER, value);
    }
  }

  @Override
  public Bundle getExtras() {
    return mBinderExtra;
  }
}